cc-pocket · phase 2 · direction a locked

A Master Core v1

Native Professional Utility, taken to implementation fidelity. List-first, container-free, hierarchy from type and hairlines, one elevated surface only where the product interrupts. This file carries foundations, the three dark master screens and component anatomy. Responsive, stress and legacy proof frames follow in a second file.

3 masters
390 × 844
dark first
1:1 scale
F

Foundations

Paired dark and light tokens. Dark is the default surface.
Dark · default
base#0B0B0C
surface#141417
raised#1B1B1F
hairline#FFF 14%
primary txt#F3F3F4 · 17.4:1
secondary#B4B5BC · 8.6:1
muted#8C8D95 · 5.1:1
accent#E2795A
success#5CB582 · 7.8:1
attention#E9B45C · 11.1:1
danger#E97462 · 6.5:1
info#7FAEE0 · 8.2:1
Light · paired
base#FCFBFA
surface#F4F2EF
raised#FFFFFF
hairline#141410 16%
primary txt#17161A · 17.1:1
secondary#4B4A50 · 8.9:1
muted#6B6970 · 5.4:1
accent#A9482A · 5.9:1
success#1F7A4D · 4.9:1
attention#8A5A08 · 5.5:1
danger#A3311F · 7.0:1
info#2A5D96 · 7.2:1
Type roles
Screen title 33/36
Row title 17.5/23 · semibold
Body and preview 15.5/23
Section label 11 · +.13em
Mono 12.5 — command · path · branch · counts

UI font is the platform system face — SF on iOS, Roboto on Android. No branded display face. Monospace is reserved for technical strings the daemon supplies verbatim.

Grid & shape
4pt base, 8pt main rhythm
gutter 24 · row 14/16 · block 22
radius 11 control · 13 button
22 sheet top · 0 for list rows
48 Every control is at least 48×48dp of hit area, even when its ink is smaller.
Status marks
Online / running — filled dot
Approval / answer — diamond
Failure — square
Complete / idle — ring

Shape and a written label carry every state. Colour is confirmation, never the only signal.

Motion
sheet in 220ms ease-out
state change 120ms linear
countdown ticks per second
list never animates reorder
haptic once on approval arrival
prefers-reduced-motion

Pulsing dots become static. The sheet cross-fades instead of sliding. The countdown still updates its number and bar — it is data, not decoration.

A

Master screens · dark

One session, one truth: it is running and it is blocked on approval 1 of 3.
01 · Sessions
9:41

Sessions

Panda · MacBook Pro · online
cc-pocket · feat/auth-refactor
~/proj/app/cc-pocket
Active
Refactor auth module
Review the concurrency around the refresh mutex before I open the PR.
Claude · feat/auth-refactor
Approval required Review
Recent
Fix flaky socket test
The reconnect test still fails intermittently on CI.
Codex · fix/socket-test · 2h ago
Release notes 1.6
Summarize the user-visible changes from the last 12 commits.
Claude · main · yesterday
+New session
Rules
Context wraps on fixed lines — identity, then project and branch, then the path row, which is tappable to expand and long-press to copy at a full 48dp.

No run duration is printed: runStartedAt is not guaranteed, so the row states what is true and stops.

The pending approval is the loudest thing on the screen: filled terracotta on the row that owns it. New session stays a hairline button so it is reachable without competing.

Bottom dock reserves 12pt above the home indicator, and the list pads its last row so nothing hides beneath the dock.
02 · Chat · approval required
9:41
Refactor auth module
Claude · default permission
Panda · MacBook Pro
cc-pocket · feat/auth-refactor
~/proj/app/cc-pocket
Approval required
Upload coverage to Codecov Review
Running · 1 approval blocking another action
You
add a unit test for the stream parser
Claude
The parser now emits exactly one event when a frame is split across chunks.
Tool
Bash ./gradlew :protocol:test 42 passed
Claude
I'm checking the remaining call sites that read TokenStore
+ Message Claude
Composer enabled · your message queues behind the approval
Rules
Chat never shows Running alone while an approval is outstanding. Approval required leads; Running is demoted to a qualifying line and only appears because other work genuinely continues.

Source labels sit above each turn as quiet uppercase text — enough structure to tell User, Claude and Tool apart without a fixed timeline gutter.

No timestamps are drawn, because none are supplied. Streaming caret stays only while the assistant is genuinely producing tokens.

Composer states its own condition in words. Every icon control is a real 48dp square even where the glyph is 12–26px.
03 · Secure approval sheet
9:41
Refactor auth module
Claude · default permission
cc-pocket · feat/auth-refactor
The parser now emits exactly one event when a frame is split across chunks.
Approval required 1 of 3
18s automatically denied when time runs out
Runs the project test suite, then uploads its coverage report to Codecov.
Run command Bash
Medium risk external upload
./gradlew test && bash scripts/upload-coverage.sh
Permission This task only
Effects Runs tests in cc-pocket
Uploads coverage externally
Project ~/proj/app/cc-pocket
Evidencescript contents, destination and affected files
Recommended: Allow for this task
The command stays in this project, but uploads coverage to Codecov.
Deny
Allow for this task
Rules
Non-dismissible by construction. No grabber, no swipe-down, scrim taps are swallowed, and system back is intercepted — it never resolves silently as Deny. Only Deny, Allow or the timer ends this sheet, and the timer fails closed.

Three zones: a pinned header holding state, queue and countdown; a scrolling body; a pinned decision bar. Expanding Evidence grows the body only, so the actions can never be pushed off-screen.

Consequence in plain language comes first, identity and risk second, the literal command third. Permission duration and effects are distinct rows because they answer different questions.

Deny and Allow are equal-width and equal-height. Allow carries accent fill, Deny carries a 3:1 boundary, and neither animates. On a danger-class request the recommendation flips to Deny and the fill moves with it.
C

Component anatomy

Named parts behind the three screens above.
Shell
PocketScaffold
ScreenHeader
ContextBlock
PathRow

Scaffold owns safe-area insets and the bottom dock reservation. ContextBlock takes ordered lines and drops any it has no data for.

List
HairlineList
SessionRow
MetadataLine
StateAction

SessionRow is mark, title, preview, metadata and an optional StateAction. Only the highest-priority state renders an action.

Stream
ChatStream
UserTurn · AssistantTurn
ToolEvent
ComposerDock

ToolEvent is a hairline-bounded band, never a card. ComposerDock exposes its enabled state as text, not only as opacity.

Approval
ApprovalContent
ApprovalSheetPresentation
RiskBadge · QueueProgress
Countdown · EvidenceDisclosure
DecisionBar

Content is separated from presentation so the same approval can render in a sheet, a notification or a full screen without changing its safety contract.

Second file carries the four proof frames — Sessions light, Chat at 360px with 200% type, approval stress state, legacy missing-data approval — plus the full data-truth contract.